import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class BillingCalculator {

    // 计算调整后的通话时长（分钟）
    public int calculateAdjustedDuration(LocalDateTime start, LocalDateTime end) {
        long totalMinutes = ChronoUnit.MINUTES.between(start, end);
        // 春季DST调整
        if (isSpringDSTAdjustment(start, end)) {
            totalMinutes -= 60;
        }
        // 秋季DST调整
        else if (isFallDSTAdjustment(start, end)) {
            totalMinutes += 60;
        }
        return (int) Math.max(totalMinutes, 1); // 通话时长至少为1分钟
    }

    // 根据调整后的通话时长计算费用
    public double calculateCharge(int adjustedMinutes) {
        if (adjustedMinutes <= 20) {
            return Math.max(0.05 * adjustedMinutes, 0.05);
        } else {
            return 1.00 + 0.10 * (adjustedMinutes - 20);
        }
    }

    // 判断是否为春季DST调整
    private boolean isSpringDSTAdjustment(LocalDateTime start, LocalDateTime end) {
        return start.getMonthValue() == 3 && start.getDayOfMonth() == getLastSundayOfMonth(start.getYear(), 3)
                && start.getHour() < 2 && end.isAfter(start.withHour(3));
    }

    // 判断是否为秋季DST调整
    private boolean isFallDSTAdjustment(LocalDateTime start, LocalDateTime end) {
        return end.getMonthValue() == 11 && end.getDayOfMonth() == getLastSundayOfMonth(end.getYear(), 11)
                && start.getHour() < 2 && end.isAfter(start.withHour(2));
    }

    // 获取指定月份最后一个星期日的日期
    private int getLastSundayOfMonth(int year, int month) {
        LocalDateTime lastDayOfMonth = LocalDateTime.of(year, month, java.time.Month.of(month).length(java.time.Year.isLeap(year)), 0, 0);
        int delta = java.time.DayOfWeek.SUNDAY.getValue() - lastDayOfMonth.getDayOfWeek().getValue();
        return lastDayOfMonth.plusDays(delta).getDayOfMonth();
    }
}
